package cases

import (
	"context"
	"github.com/neo4j/neo4j-go-driver/v5/neo4j"
	"go.uber.org/zap"
	"neo4j-go-try/internal/db"
	"neo4j-go-try/internal/errors"
)

type Neo4jCase struct {
	slog *zap.SugaredLogger
	*db.DAO
	*db.Neo
}

func NewNeo4jCase(slog *zap.SugaredLogger, dao *db.DAO, neo *db.Neo) *Neo4jCase {
	return &Neo4jCase{
		slog: slog,
		DAO:  dao,
		Neo:  neo,
	}
}

func (s *Neo4jCase) RunCase_FindDirectorByMovieTitle(ctx context.Context, title string) {
	result, err := s.ExecuteQuery(ctx,
		`
	MATCH (p:Person)-[:DIRECTED]->(:Movie {title: $title})
	RETURN p
	`,
		map[string]any{"title": title},
	)
	errors.PanicOnErr(err)
	for _, record := range result.Records {
		s.slog.Info(record.AsMap())
	}
}

func (s *Neo4jCase) RunCase_FindPersonByName(ctx context.Context, name string) {
	session := s.CreateSession(ctx, "neo4j")
	result, err := session.Run(ctx,
		`
	MATCH (a:Person {name:$name}) 
	RETURN a
	`,
		map[string]any{"name": name},
	)
	errors.PanicOnErr(err)
	people, err := neo4j.CollectTWithContext[neo4j.Node](ctx, result,
		func(record *neo4j.Record) (neo4j.Node, error) {
			person, _, err := neo4j.GetRecordValue[neo4j.Node](record, "a")
			return person, err
		})
	errors.PanicOnErr(err)
	session.Close(ctx)
	s.slog.Info(people)
}

func (s *Neo4jCase) RunCase_CreateUser(ctx context.Context) {
	result, err := s.CreateUser(ctx, db.CreateUserParam{
		Name:     "admin2",
		Mobile:   "18005884569",
		PassHash: "",
	})
	errors.PanicOnErr(err)
	s.slog.Info("User=>%#v", result)
}

func (s *Neo4jCase) RunCase_GetUser(ctx context.Context) {
	result, err := s.GetUserByID(ctx, "4:5b83c761-60a7-4440-90f7-f6b581d351c3:11")
	errors.PanicOnErr(err)
	s.slog.Info("User=>%#v", result)
}

func (s *Neo4jCase) RunCase_ListUsersWithRole(ctx context.Context) {
	result, err := s.ListUsersWithRoles(ctx)
	errors.PanicOnErr(err)
	s.slog.Infof("UsersWithRole=>%#v", result)
}

func (s *Neo4jCase) RunCase_PagedUsersWithRole(ctx context.Context) {
	result, err := s.PagedUsersWithRoles(ctx, db.Pager{PageNo: 1, PageSize: 4})
	errors.PanicOnErr(err)
	s.slog.Infof("UsersWithRole2=>%d", result.Total)
	for _, row := range result.Rows {
		s.slog.Infof("UsersWithRole2=>%+v", row)
	}
}

func (s *Neo4jCase) RunCase_CreateAdminRole(ctx context.Context) {
	result, err := s.CreateRole(ctx, db.CreateRoleParam{
		Name: "管理员",
	})
	errors.PanicOnErr(err)
	s.slog.Info("Role=>%#v", result)
}

func (s *Neo4jCase) RunCase_CreateNormalRole(ctx context.Context) {
	result, err := s.CreateRole(ctx, db.CreateRoleParam{
		Name: "普通用户",
	})
	errors.PanicOnErr(err)
	s.slog.Info("Role=>%#v", result)
}

func (s *Neo4jCase) RunCase_GetRole(ctx context.Context) {
	result, err := s.GetRoleByID(ctx, "4:5b83c761-60a7-4440-90f7-f6b581d351c3:12")
	errors.PanicOnErr(err)
	s.slog.Info("Role=>%#v", result)
}

func (s *Neo4jCase) RunCase_CreateUserBelongsToAdmin(ctx context.Context) {
	result, err := s.CreateUserBelongsToRole(ctx, db.CreateUserBelongsToRoleParam{
		UserID: "4:5b83c761-60a7-4440-90f7-f6b581d351c3:11",
		RoleID: "4:5b83c761-60a7-4440-90f7-f6b581d351c3:12",
	})
	errors.PanicOnErr(err)
	s.slog.Info("UserBelongsToRole=>%#v", result)
}

func (s *Neo4jCase) RunCase_CreateUserBelongsToNormal(ctx context.Context) {
	result, err := s.CreateUserBelongsToRole(ctx, db.CreateUserBelongsToRoleParam{
		UserID: "4:5b83c761-60a7-4440-90f7-f6b581d351c3:11",
		RoleID: "4:5b83c761-60a7-4440-90f7-f6b581d351c3:14",
	})
	errors.PanicOnErr(err)
	s.slog.Info("UserBelongsToRole=>%#v", result)
}
